﻿namespace CatClient.Message.Spi.Internals
{
    using CatClient.Message;
    using CatClient.Message.Internals;
    using CatClient.Message.Spi;
    using System;
    using System.IO;

    public class DefaultMessageProducer : IMessageProducer
    {
        private readonly IMessageManager _manager;

        public DefaultMessageProducer(IMessageManager manager)
        {
            this._manager = manager;
        }

        public string CreateMessageId() => 
            this._manager.GetMessageIdFactory().GetNextId();

        public virtual void LogError(Exception cause)
        {
            if (cause != null)
            {
                bool flag = false;
                if (cause.Data.Contains("CatIgnore") && (cause.Data["CatIgnore"] is bool))
                {
                    flag = (bool) cause.Data["CatIgnore"];
                }
                if (!flag)
                {
                    StringWriter writer = new StringWriter();
                    try
                    {
                        writer.WriteLine(cause.Message);
                        writer.WriteLine(cause.StackTrace);
                        for (Exception exception = cause.InnerException; exception != null; exception = exception.InnerException)
                        {
                            writer.WriteLine("-------------------------------------------------------------------");
                            writer.WriteLine(exception.Message);
                            writer.WriteLine(exception.StackTrace);
                        }
                    }
                    catch
                    {
                    }
                    this.LogEvent("Error", cause.GetType().FullName, "ERROR", writer.ToString());
                }
            }
        }

        public virtual void LogEvent(string type, string name, string status, string nameValuePairs)
        {
            IEvent event2 = this.NewEvent(type, name);
            if (!string.IsNullOrEmpty(nameValuePairs))
            {
                event2.AddData(nameValuePairs);
            }
            event2.Status = status;
            event2.Complete();
        }

        public virtual void LogHeartbeat(string type, string name, string status, string nameValuePairs)
        {
            IHeartbeat heartbeat = this.NewHeartbeat(type, name);
            if (!string.IsNullOrEmpty(nameValuePairs))
            {
                heartbeat.AddData(nameValuePairs);
            }
            heartbeat.Status = status;
            heartbeat.Complete();
        }

        public virtual void LogMetric(string name, string status, string nameValuePairs)
        {
            string type = string.Empty;
            IMetric metric = this.NewMetric(type, name);
            if (!string.IsNullOrWhiteSpace(nameValuePairs))
            {
                metric.AddData(nameValuePairs);
            }
            metric.Status = status;
            metric.Complete();
        }

        public virtual void LogTrace(string type, string name, string status, string nameValuePairs)
        {
            ITrace trace = this.NewTrace(type, name);
            if (!string.IsNullOrEmpty(nameValuePairs))
            {
                trace.AddData(nameValuePairs);
            }
            trace.Status = status;
            trace.Complete();
        }

        public IAsyncForkedTransaction NewAsyncForkedTransaction(string type, string name)
        {
            if (!this._manager.HasContext())
            {
                this._manager.Setup();
            }
            if (!this._manager.CatEnabled)
            {
                return NullMessage.ASYNCFORKEDTRANSACTION;
            }
            IMessageTree threadLocalMessageTree = this._manager.ThreadLocalMessageTree;
            if (threadLocalMessageTree.MessageId == null)
            {
                threadLocalMessageTree.MessageId = this.CreateMessageId();
            }
            IAsyncForkedTransaction transaction = new AsyncForkedTransaction(type, name, this._manager);
            if (this._manager is DefaultMessageManager)
            {
                ((DefaultMessageManager) this._manager).LinkAsRunAway(transaction);
            }
            this._manager.Start(transaction, true);
            transaction.Start();
            return transaction;
        }

        public virtual IEvent NewEvent(string type, string name)
        {
            if (!this._manager.HasContext())
            {
                this._manager.Setup();
            }
            if (this._manager.CatEnabled)
            {
                IEvent message = new DefaultEvent(type, name, null);
                this._manager.Add(message);
                return message;
            }
            return NullMessage.EVENT;
        }

        public IForkedTransaction NewForkedTransaction(string type, string name)
        {
            if (!this._manager.HasContext())
            {
                this._manager.Setup();
            }
            if (!this._manager.CatEnabled)
            {
                return NullMessage.FORKEDTRANSACTION;
            }
            IMessageTree threadLocalMessageTree = this._manager.ThreadLocalMessageTree;
            if (threadLocalMessageTree.MessageId == null)
            {
                threadLocalMessageTree.MessageId = this.CreateMessageId();
            }
            IForkedTransaction transaction = new DefaultForkedTransaction(type, name, this._manager);
            if (this._manager is DefaultMessageManager)
            {
                ((DefaultMessageManager) this._manager).LinkAsRunAway(transaction);
            }
            this._manager.Start(transaction, true);
            return transaction;
        }

        public virtual IHeartbeat NewHeartbeat(string type, string name)
        {
            if (!this._manager.HasContext())
            {
                this._manager.Setup();
            }
            if (this._manager.CatEnabled)
            {
                IHeartbeat message = new DefaultHeartbeat(type, name, null);
                this._manager.Add(message);
                return message;
            }
            return NullMessage.HEARTBEAT;
        }

        public virtual IMetric NewMetric(string type, string name)
        {
            if (!this._manager.HasContext())
            {
                this._manager.Setup();
            }
            if (this._manager.CatEnabled)
            {
                IMetric message = new DefaultMetric(string.IsNullOrWhiteSpace(type) ? string.Empty : type, name, null);
                this._manager.Add(message);
                return message;
            }
            return NullMessage.METRIC;
        }

        public ITaggedTransaction NewTaggedTransaction(string type, string name, string tag)
        {
            if (!this._manager.HasContext())
            {
                this._manager.Setup();
            }
            if (!this._manager.CatEnabled)
            {
                return NullMessage.TAGGEDTRANSACTION;
            }
            IMessageTree threadLocalMessageTree = this._manager.ThreadLocalMessageTree;
            if (threadLocalMessageTree.MessageId == null)
            {
                threadLocalMessageTree.MessageId = this.CreateMessageId();
            }
            ITaggedTransaction transaction = new DefaultTaggedTransaction(type, name, tag, this._manager);
            this._manager.Start(transaction, true);
            return transaction;
        }

        public virtual ITrace NewTrace(string type, string name)
        {
            if (!this._manager.HasContext())
            {
                this._manager.Setup();
            }
            if (this._manager.CatEnabled)
            {
                ITrace message = new DefaultTrace(type, name, null);
                this._manager.Add(message);
                return message;
            }
            return NullMessage.TRACE;
        }

        public virtual ITransaction NewTransaction(string type, string name)
        {
            if (!this._manager.HasContext())
            {
                this._manager.Setup();
            }
            if (this._manager.CatEnabled)
            {
                ITransaction transaction = new DefaultTransaction(type, name, this._manager);
                this._manager.Start(transaction, false);
                return transaction;
            }
            return NullMessage.TRANSACTION;
        }

        public virtual ITransaction NewTransaction(ITransaction parent, string type, string name)
        {
            if (!this._manager.HasContext())
            {
                this._manager.Setup();
            }
            if (this._manager.CatEnabled && (parent != null))
            {
                ITransaction message = new DefaultTransaction(type, name, this._manager);
                parent.AddChild(message);
                message.Standalone = false;
                return message;
            }
            return NullMessage.TRANSACTION;
        }
    }
}

